# -*- coding:utf-8 -*-
import argparse
import shutil
from os import mkdir, rename, listdir, access, F_OK
from os.path import isfile
from Packages.AppData import *
from sys import exit
import datetime
import yaml


def GetDateNow(ReturnList=False):
    date = datetime.datetime.today().date()
    if ReturnList:
        return [date.year, date.month, date.day]
    else:
        return f"{date.year}-{date.month}-{date.day}"


def GetTimeNow(ReturnList=False):
    time = datetime.datetime.today().time()
    if ReturnList:
        return [time.hour, time.minute, time.second]
    else:
        return f"{time.hour}-{time.minute}-{time.second}"


_ = [path for path in listdir('/')]
BaseProtectPath = [path for path in listdir('/')]
for path in _:
    BaseProtectPath.append(f"/{path}")
BaseProtectPath.extend(['/', '/.'])

AppData = appdata('safe-rm')
if AppData.IsApplicationDirectoryExists():
    pass
else:
    AppData.CreateApplicationDataDir()
if AppData.IsApplicationConfigFileExists():
    config = AppData.LoadApplicationConfigFile()
else:
    _, config = AppData.CreateApplicationConfigFile({
        'options': {
            'version': '0.0.1',
            'language': 'en',
            'trash-path':
            AppData.CreateDirectoryAtApplicationDirectory('trash'),
            'install-path': '/usr/share/SafeRemove',
            'protect-path': None,
            'debug': False
        }
    })
    config['options']['protect-path'] = BaseProtectPath
    AppData.WriteApplicationConfigFile(config)

with open(f"{config['options']['install-path']}/Languages/{config['options']['language']}.yml") as f:
    LANGUAGE = yaml.safe_load(f.read())

ArgParser = argparse.ArgumentParser(
    prog="safe-rm",
    formatter_class=argparse.RawDescriptionHelpFormatter,
    usage=LANGUAGE['Language']['usage'],
    description=LANGUAGE['Language']['description'],
    epilog=LANGUAGE["Language"]['epilog'].format(
        config['options']['trash-path'], ))

NonCoexistentGroup = ArgParser.add_mutually_exclusive_group()
NonCoexistentGroup2 = ArgParser.add_mutually_exclusive_group()

# 添加选项
# action: 动作
# help: -h 选项下显示的内容
NonCoexistentGroup.add_argument(
    "-f",
    "--force",
    action="store_true",
    help=LANGUAGE['Language']['force-delete'],
)

NonCoexistentGroup.add_argument(
    "-i",
    action="store_true",
    help=LANGUAGE['Language']['before-delete-question'],
)

NonCoexistentGroup2.add_argument("--ChangeLanguage",
                                 type=str,
                                 default=None,
                                 choices=['en', 'zh-cn'],
                                 help=LANGUAGE['Language']['change-language'])

NonCoexistentGroup2.add_argument(
    "-c",
    "--clear-trash-can",
    action="store_true",
    help=LANGUAGE['Language']['clear-trash-can'],
)

NonCoexistentGroup2.add_argument("--add-protect-path",
                                 type=str,
                                 action='extend',
                                 nargs='+',
                                 metavar=LANGUAGE['Language']['path'],
                                 dest='add_protect_path',
                                 help=LANGUAGE['Language']['add-protect-path'])

NonCoexistentGroup2.add_argument("--debug",
                                 action='store_true',
                                 help=LANGUAGE['Language']['debug'])

NonCoexistentGroup2.add_argument(
    "--remove-protect-path",
    type=str,
    action='extend',
    nargs='+',
    metavar=LANGUAGE['Language']['path'],
    dest='remove_protect_path',
    help=LANGUAGE['Language']['remove-protect-path'])

ArgParser.add_argument(
    "-r",
    "--recursive",
    default=True,
    action="store_true",
    help=LANGUAGE['Language']['recursive'],
)

ArgParser.add_argument(
    "-d",
    "--dir",
    action="store_true",
    help=LANGUAGE['Language']['dir'],
)

NonCoexistentGroup2.add_argument(
    "--version",
    action="version",
    version=f"%(prog)s {config['options']['version']}",
    help=LANGUAGE['Language']['version'],
)

ArgParser.add_argument("files",
                       type=str,
                       action='extend',
                       nargs='*',
                       help=LANGUAGE['Language']['file'])

ArgParser.add_argument("--recovery",
                       type=str,
                       action='extend',
                       nargs='*',
                       metavar=LANGUAGE['Language']['restore-dest'],
                       dest='recovery_path',
                       help=LANGUAGE['Language']['restore'])

args = ArgParser.parse_args()
if args.force:
    args.i = False
else:
    args.i = True

if args.ChangeLanguage or args.clear_trash_can:
    pass

if args.debug and not (config['options']['debug']):
    config['options']['debug'] = True
    AppData.WriteApplicationConfigFile(config)
elif args.debug and config['options']['debug']:
    config['options']['debug'] = False
    AppData.WriteApplicationConfigFile(config)



if config['options']['debug']:
    print(args)


def ChangeLanguage(language):
    print(language)
    global AppData, config
    config['options']['language'] = language
    AppData.WriteApplicationConfigFile(config)


def MoveToTrash(Path, isForce, isFile, removeEmptyDir):
    file_translate = LANGUAGE['Language']['file']
    directory_translate = LANGUAGE['Language']['directory']
    if Path == '/' or Path == '/.':
        print(LANGUAGE['Language']['recursive-on-root'])
    if isForce:
        if not removeEmptyDir:
            try:
                if access(Path, F_OK):
                    if not (Path in config['options']['protect-path']):
                        shutil.move(Path, config['options']['trash-path'])
                    else:
                        answer = input(
                            "safe-rm: " + LANGUAGE['Language']
                            ['try-delete-protect-path'].format(Path))
                        if answer == '' or answer == 'n' or answer == 'N':
                            return False
                        elif answer == 'Y' or answer == 'y':
                            shutil.move(Path, config['options']['trash-path'])
                else:
                    raise FileNotFoundError()
            except FileNotFoundError:
                return False
            except PermissionError or FileExistsError:
                print(
                    f"safe-rm: error: {LANGUAGE['Language']['error']['no-permission']}"
                )
                return False
            except shutil.Error or shutil.SameFileError:
                rename(
                    f"{config['options']['trash-path']}/{Path}",
                    f"{config['options']['trash-path']}/{Path}-{GetDateNow()}-{GetTimeNow()}"
                )
                shutil.move(Path, config['options']['trash-path'])
        else:
            try:
                if listdir(Path) != [] and not (access(Path, F_OK)):
                    raise OSError()
                elif listdir(Path) == [] and access(Path, F_OK):
                    shutil.move(Path, config['options']['trash-path'])
                else:
                    raise FileNotFoundError()
            except FileNotFoundError:
                pass
            except OSError:
                print(
                    f"safe-rm: error: {LANGUAGE['Language']['error']['directory-not-empty'].format(Path)}"
                )
                return False
            except shutil.Error or shutil.SameFileError:
                rename(
                    f"{config['options']['trash-path']}/{Path}",
                    f"{config['options']['trash-path']}/{Path}-{GetDateNow()}-{GetTimeNow()}"
                )
                shutil.move(Path, config['options']['trash-path'])
    else:
        if access(Path, F_OK):
            if not (Path in config['options']['protect-path']):
                answer = input("safe-rm: " +
                               LANGUAGE['Language']['delete-question'].format(
                                   file_translate
                                   if isFile else directory_translate, path))
            else:
                answer = input("safe-rm: " + LANGUAGE['Language']
                               ['try-delete-protect-path'].format(Path))
            if answer == '' or answer == 'n' or answer == 'N':
                return False
            elif answer == 'Y' or answer == 'y':
                if not removeEmptyDir:
                    try:
                        shutil.move(Path, config['options']['trash-path'])
                    except FileNotFoundError:
                        print(
                            f"safe-rm: error: {LANGUAGE['Language']['error']['file-not-found'].format(Path)}"
                        )
                        return False
                    except shutil.Error or shutil.SameFileError:
                        rename(
                            f"{config['options']['trash-path']}/{Path}",
                            f"{config['options']['trash-path']}/{Path}-{GetDateNow()}-{GetTimeNow()}"
                        )
                        shutil.move(Path, config['options']['trash-path'])
                else:
                    try:
                        if listdir(Path) != []:
                            raise OSError()
                        else:
                            shutil.move(Path, config['options']['trash-path'])
                    except FileNotFoundError:
                        print(
                            f"safe-rm: error: {LANGUAGE['Language']['error']['file-not-found'].format(Path)}"
                        )
                        return False
                    except OSError:
                        print(
                            f"safe-rm: error: {LANGUAGE['Language']['error']['directory-not-empty'].format(Path)}"
                        )
                        return False
                    except shutil.Error or shutil.SameFileError:
                        rename(
                            f"{config['options']['trash-path']}/{Path}",
                            f"{config['options']['trash-path']}/{Path}-{GetDateNow()}-{GetTimeNow()}"
                        )
                        shutil.move(Path, config['options']['trash-path'])
            else:
                print(
                    f"safe-rm: {LANGUAGE['Language']['error']['invaild-operation']}"
                )
                return False
        else:
            print(
                f"safe-rm: error: {LANGUAGE['Language']['error']['file-not-found'].format(Path)}"
            )
            return False


def ClearTrashFileAndPath():
    global config
    try:
        shutil.rmtree(config['options']['trash-path'])
    except PermissionError:
        raise PermissionError(
            'No permission to remove trash file.Please run safe-rm on root or sudo'
        )
    mkdir(config['options']['trash-path'])
    return True


def AddProtectPath(Path):
    global AppData, config
    if Path in config['options']['protect-path']:
        print(
            f"safe-rm: {LANGUAGE['Language']['path-is-already-in-protect-path']}"
        )
        return True
    else:
        answer = input(
            f"safe-rm: {LANGUAGE['Language']['add-protect-path-question'].format(Path)}"
        )
        if answer == '' or answer == 'n' or answer == 'N':
            return False
        elif answer == 'y' or answer == 'Y':
            config['options']['protect-path'].append(Path)
        else:
            print(
                f"safe-rm: {LANGUAGE['Language']['error']['invaild-operation']}"
            )
            return False

    return AppData.WriteApplicationConfigFile(config)


def RemoveProtectPath(Path):
    global AppData, config
    if (Path in BaseProtectPath):
        print(LANGUAGE['Language']['error']
              ['try-remove-system-path-from-protected-path'].format(
                  Path, Path))
        return False
    answer = input(
        f"safe-rm: {LANGUAGE['Language']['remove-protect-path-question'].format(Path)}"
    )
    if answer == '' or answer == 'n' or answer == 'N':
        return False
    elif answer == 'Y' or answer == 'y':
        if Path in config['options']['protect-path']:
            config['options']['protect-path'].remove(Path)
        else:
            print(
                f"safe-rm: {LANGUAGE['Language']['error']['path-is-no-longer-in-protected-path']}"
            )
            return False
    else:
        print(f"safe-rm: {LANGUAGE['Language']['error']['invaild-operation']}")
        return False
    return AppData.WriteApplicationConfigFile(config)


def RecoveryFiles(Path):
    if access(f"{config['options']['trash-path']}/{Path}", F_OK):
        answer = input(
            f"safe-rm: {LANGUAGE['Language']['recovery-files-question'].format(Path)}"
        )
    else:
        print(f"safe-rm: {LANGUAGE['Language']['error']['file-not-found'].format(Path)}")
        return False
    if answer == '' or answer == 'n' or answer == 'N':
        return False
    elif answer == 'Y' or answer == 'y':
        try:
            shutil.move(f"{config['options']['trash-path']}/{Path}", './')
        except FileNotFoundError:
            print(
                f"safe-rm: {LANGUAGE['Language']['error']['file-not-found'].format(Path)}")
            return False
        except shutil.Error:
            rename(
                f"{config['options']['trash-path']}/{Path}",
                f"{config['options']['trash-path']}/{Path}-{GetDateNow()}-{GetTimeNow()}"
            )
            shutil.move(f"{config['options']['trash-path']}/{Path}", './')
    else:
        print(f"safe-rm: {LANGUAGE['Language']['error']['invaild-operation']}")
        return False
    return True


if __name__ == '__main__':
    if args.ChangeLanguage:
        ChangeLanguage(args.ChangeLanguage)
        exit(0)
    if args.clear_trash_can:
        ClearTrashFileAndPath()
        exit(0)
    if args.add_protect_path:
        for path in args.add_protect_path:
            AddProtectPath(path)
        exit(0)
    if args.remove_protect_path:
        for path in args.remove_protect_path:
            RemoveProtectPath(path)
    if args.recovery_path:
        for path in args.recovery_path:
            RecoveryFiles(path)
    for path in args.files:
        if path:
            MoveToTrash(path, args.force, isfile(path), args.dir)
    exit(0)
